package com.example.controller;

import org.elasticsearch.action.search.SearchRequestBuilder;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.search.SearchType;
import org.elasticsearch.client.transport.TransportClient;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.query.RangeQueryBuilder;
import org.elasticsearch.search.sort.FieldSortBuilder;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;

import lombok.extern.slf4j.Slf4j;

import static org.elasticsearch.index.query.QueryBuilders.matchQuery;

/**
 * 复习昨天写的query查询
 *
 * @author 夏智峰
 * @create 2018-03-14 10:10
 */
@Slf4j
@RestController
@RequestMapping("/review")
public class ClientReviewQueryController {

  @Autowired
  private TransportClient client;

  /**
   * @desc 简单查询
   * @author 夏智峰
   * @create 2018/3/14 10:13
  **/
  @GetMapping("/easy")
  public ResponseEntity easyQuery() {
    SearchResponse result = client.prepareSearch().get();
    List<Map<String, Object>> mapList = new ArrayList<>();
    result.getHits().forEach(hit -> {
      log.info(hit.getSourceAsString());
      mapList.add(hit.getSourceAsMap());
    });
    return new ResponseEntity(mapList, HttpStatus.OK);
  }

  /**
   * @desc 短语搜索
   * @author 夏智峰
   * @create 2018/3/14 15:15
  **/

  /**
   * @desc 根据书籍名字查询
   * @author 夏智峰
   * @create 2018/3/14 10:15
  **/
  @GetMapping("/query_title/{index}/{type}")
  public ResponseEntity queryTitle(@PathVariable(value = "index") String index,
                                  @PathVariable(value = "type") String type, String title) {
    SearchRequestBuilder builder = client.prepareSearch(index)
            .setTypes(type)
            .setSearchType(SearchType.DFS_QUERY_THEN_FETCH)
            .setQuery(QueryBuilders.matchQuery("title", title))
            .setFrom(0)
            .setSize(10);
    log.info(builder.toString());
    SearchResponse response = builder.get();
    List<Map<String, Object>> mapList = new ArrayList<>();
    response.getHits().forEach(hit -> {
      log.info(hit.getSourceAsString());
      mapList.add(hit.getSourceAsMap());
    });
    return new ResponseEntity(mapList, HttpStatus.OK);
  }

  /**
   * @desc 多条件查询
   * @author 夏智峰
   * @create 2018/3/14 10:28
  **/
  @GetMapping("/bool/{index}/{type}")
  public ResponseEntity boolQUery(@PathVariable(value = "index") String index,
                                  @PathVariable(value = "type") String type, String title,
                                  String author, Integer gtWordCount, Integer ltWordCount) {
    BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();

    if (Objects.nonNull(title)) {
      boolQuery.must(QueryBuilders.matchQuery("title", title));
    }

    RangeQueryBuilder rangeQuery = QueryBuilders.rangeQuery("wordCount");
    if (Objects.nonNull(gtWordCount)) {
      rangeQuery.from(gtWordCount);
    }
    if (Objects.nonNull(ltWordCount)) {
      rangeQuery.to(ltWordCount);
    }
    boolQuery.filter(rangeQuery);

    SearchRequestBuilder builder = client.prepareSearch(index)
            .setTypes(type)
            .setSearchType(SearchType.DFS_QUERY_THEN_FETCH)
            .setQuery(boolQuery)
            .setFrom(0)
            .setSize(10);
    log.info(builder.toString());
    SearchResponse response = builder.get();

    List<Map<String, Object>> mapList = new ArrayList<>();
    response.getHits().forEach(hit -> {
      log.info(hit.getSourceAsString());
      mapList.add(hit.getSourceAsMap());
    });
    return new ResponseEntity(mapList, HttpStatus.OK);
  }

  /**
   * @desc 查询age大于30，last_name为Smith的员工，需要添加过滤器filter,gt大于，gte大于等于
   * @author 夏智峰
   * @create 2018/3/14 13:30
  **/
  @GetMapping("/megacorp")
  public ResponseEntity megacorp() {
    BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
    boolQuery.must(QueryBuilders.matchQuery("last_name", "Smith"));
    RangeQueryBuilder rangeQuery = QueryBuilders.rangeQuery("age");
    rangeQuery.from(30);
    boolQuery.filter(rangeQuery);
    SearchRequestBuilder builder = client.prepareSearch("megacorp")
            .setTypes("employee")
            .setSearchType(SearchType.DFS_QUERY_THEN_FETCH)
            .setQuery(boolQuery)
            .setFrom(0)
            .setSize(10);
    log.info(boolQuery.toString());
    SearchResponse response = builder.get();

    List<Map<String, Object>> mapList = new ArrayList<>();
    response.getHits().forEach(hit -> {
      log.info(hit.getSourceAsString());
      mapList.add(hit.getSourceAsMap());
    });
    return new ResponseEntity(mapList, HttpStatus.OK);
  }


  /**
   * @desc 滚动查询
   * @author 夏智峰
   * @create 2018/3/14 14:15
   **/
  @GetMapping("/scroll")
  public ResponseEntity scroll() {
    QueryBuilder queryBuilder  = matchQuery("author", "吃");
    SearchResponse response = client.prepareSearch("book")
            .addSort(FieldSortBuilder.DOC_FIELD_NAME, SortOrder.ASC)
            .setScroll(new TimeValue(12000))
            .setQuery(queryBuilder)
            .setSize(3).get();
    List<Map<String, Object>> mapList = new ArrayList<>();
    do {
      response.getHits().forEach(hit -> {
        log.info(hit.getSourceAsString());
        mapList.add(hit.getSourceAsMap());
      });

      response = client.prepareSearchScroll(response.getScrollId())
              .setScroll(new TimeValue(12000))
              .execute().actionGet();
    } while (response.getHits().getHits().length != 0);
    return new ResponseEntity(mapList, HttpStatus.OK);
  }
}
